package com.wcq.studentbackend.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wcq.studentbackend.dto.ExamDTO;
import com.wcq.studentbackend.dto.ExamRequestDTO;
import com.wcq.studentbackend.dto.GradeDTO;
import com.wcq.studentbackend.entity.Exam;
import com.wcq.studentbackend.entity.Student;
import com.wcq.studentbackend.mapper.ExamMapper;
import com.wcq.studentbackend.mapper.GradeMapper;
import com.wcq.studentbackend.mapper.StudentMapper;
import com.wcq.studentbackend.service.ExamService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ExamServiceImpl extends ServiceImpl<ExamMapper, Exam> implements ExamService {

    // BaseMapper (this.baseMapper) 已经由 ServiceImpl 注入，即 ExamMapper

    @Autowired // Inject StudentMapper
    private StudentMapper studentMapper;

    @Autowired // Inject GradeMapper
    private GradeMapper gradeMapper;

    @Override
    public List<ExamDTO> getAllExams() {
        List<Exam> examList = list(); // list() 方法来自 IService (ServiceImpl)
        return examList.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    @Override
    public ExamDTO getExamById(Long id) {
        Exam examEntity = getById(id); // getById() 方法来自 IService
        return convertToDTO(examEntity);
    }

    @Override
    @Transactional // 建议在写操作上加上事务注解
    public ExamDTO createExam(ExamRequestDTO examRequestDTO) {
        Exam examEntity = new Exam();
        BeanUtils.copyProperties(examRequestDTO, examEntity);
        // 手动设置创建和更新时间，或者配置MyBatis-Plus自动填充
        LocalDateTime now = LocalDateTime.now();
        examEntity.setCreateTime(now);
        examEntity.setUpdateTime(now);
        
        save(examEntity); // save() 方法来自 IService
        return convertToDTO(examEntity);
    }

    @Override
    @Transactional
    public ExamDTO updateExam(Long id, ExamRequestDTO examRequestDTO) {
        Exam examEntity = getById(id);
        if (examEntity == null) {
            // 可以抛出自定义异常，例如 NotFoundException，或者返回null让Controller处理
            return null; 
        }
        BeanUtils.copyProperties(examRequestDTO, examEntity);
        examEntity.setUpdateTime(LocalDateTime.now());
        
        updateById(examEntity); // updateById() 方法来自 IService
        return convertToDTO(getById(id)); // 返回更新后的数据
    }

    @Override
    @Transactional
    public boolean deleteExam(Long id) {
        return removeById(id); // removeById() 方法来自 IService
    }

    // Helper method to convert Entity to DTO
    private ExamDTO convertToDTO(Exam examEntity) {
        if (examEntity == null) {
            return null;
        }
        ExamDTO examDTO = new ExamDTO();
        BeanUtils.copyProperties(examEntity, examDTO);
        return examDTO;
    }

    @Override
    public List<ExamDTO> getExamsByStudentStuNo(String stuNo) {
        QueryWrapper<Student> studentQueryWrapper = new QueryWrapper<>();
        studentQueryWrapper.eq("stu_no", stuNo);
        Student student = studentMapper.selectOne(studentQueryWrapper);

        if (student == null) {
            log.warn("Student not found with stuNo: {}", stuNo);
            return Collections.emptyList();
        }

        // Ensure student.getId() is converted to Long if GradeMapper expects Long
        Long studentIdAsLong = student.getId() != null ? student.getId().longValue() : null;
        if (studentIdAsLong == null) {
            log.error("Student ID is null for stuNo: {}", stuNo);
            return Collections.emptyList();
        }

        List<GradeDTO> gradeDTOs = gradeMapper.findGradesByStudentId(studentIdAsLong); // Use Long studentId
        if (gradeDTOs == null || gradeDTOs.isEmpty()) {
            log.info("No grades found for studentId: {}", studentIdAsLong);
            return Collections.emptyList();
        }

        List<Long> examIds = gradeDTOs.stream()
                                     .map(GradeDTO::getExamId)
                                     .filter(id -> id != null)
                                     .distinct()
                                     .collect(Collectors.toList());

        if (examIds.isEmpty()) {
            log.info("No unique exam IDs found from grades for studentId: {}", studentIdAsLong);
            return Collections.emptyList();
        }
        log.info("Found exam IDs: {} for studentId: {}", examIds, studentIdAsLong);

        List<Exam> exams = this.listByIds(examIds);
        if (exams == null || exams.isEmpty()) {
            log.warn("No exams found for exam IDs: {}", examIds);
            return Collections.emptyList();
        }
        log.info("Fetched {} exams for studentId: {}", exams.size(), studentIdAsLong);
        
        return exams.stream().map(this::convertToDTO).collect(Collectors.toList());
    }
} 